/*
 *  Copyright (c) 1998, Regents of the University of California
 *  All rights reserved.
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 * 
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of the University of California, Berkeley nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 * 
 *  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.demis.elf;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @version 1.0
 * @author <a href="mailto:demis27@demis27.net">Stéphane kermabon</a>
 */
public class ForeignKey {

    private String name = null;
    
    /**
     * Mapping from column reference to other column
     * Imported columns -> exported columns
     */
    private Map<ColumnReference, ColumnReference> columnsMapping = new HashMap<ColumnReference, ColumnReference>();
    /** Imported table. This table have the foreign key to the primary key of exported table. */
    private Table importedTable = null;
    /** Exported table. This table have the primary key that be exported to imported table foreign key. */
    private Table exportedTable = null;
    /** Name of exported table. Use for reading ddl. */
    private String exportedTableName;

    public ForeignKey() {
        // no op
    }

    public ForeignKey(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void addReferencedColumn(ColumnReference importedReference, ColumnReference exportedReference) {
        columnsMapping.put(importedReference, exportedReference);
    }

    public void addReferencedColumn(Column importedColumn, Column exportedColumn) {
        ColumnReference importedReference = new ColumnReference(importedColumn);
        ColumnReference exportedReference = new ColumnReference(exportedColumn);
        columnsMapping.put(importedReference, exportedReference);
        importedColumn.setNoref(false);
        exportedColumn.setNoref(false);
        importedTable = importedColumn.getTable();
        exportedTable = exportedColumn.getTable();
    }
    
    public Column getExportedColumn(Column importedColumn) {
        for (ColumnReference importedReference: columnsMapping.keySet()) {
            if (importedColumn.equals(importedReference.getColumn())) {
                return columnsMapping.get(importedReference).getColumn();
            }
        }
        return null;
    }
    
    public Column getForeignKeyColumnIfUnic() {
        return columnsMapping.values().iterator().next().getColumn();
    }
    
    public Column getPrimaryKeyColumnIfUnic() {
        return columnsMapping.keySet().iterator().next().getColumn();
    }

    public Collection<Column> getImportedColumns() {
        List<Column> columns = new ArrayList<Column>();
        for (ColumnReference importedReference: columnsMapping.keySet()) {
            columns.add(importedReference.getColumn());
        }

        return columns;
    }

    public Collection<ColumnReference> getImportedColumnReferences() {
        return columnsMapping.keySet();
    }

    public Collection<Column> getExportedColumns() {
        List<Column> columns = new ArrayList<Column>();
        for (ColumnReference importedReference: columnsMapping.keySet()) {
            columns.add(columnsMapping.get(importedReference).getColumn());
        }

        return columns;
    }

    public Collection<ColumnReference> getExportedColumnReferences() {
        return columnsMapping.values();
    }

    public int getNbColumn() {
        return columnsMapping.size();
    }

    public Table getImportedTable() {
        return importedTable;
    }

    public void setImportedTable(Table importedTable) {
        this.importedTable = importedTable;
    }

    public Table getExportedTable() {
        return exportedTable;
    }

    public void setExportedTable(Table exportedTable) {
        this.exportedTable = exportedTable;
    }

    public String getExportedTableName() {
        return exportedTableName;
    }

    public void setExportedTableName(String importedTableName) {
        this.exportedTableName = importedTableName;
    }

    @Override
    public boolean equals(Object dataBaseForeignKey) {
        return (dataBaseForeignKey instanceof ForeignKey
                && ((ForeignKey)dataBaseForeignKey).name != null
                && ((ForeignKey)dataBaseForeignKey).name.equals(name));
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }

    @Override
    public String toString() {
        StringBuffer buffer = new StringBuffer();
        buffer.append(name);
        buffer.append(":(");
        for (ColumnReference key: columnsMapping.keySet()) {
            buffer.append(key.getColumn());
            buffer.append("->");
            buffer.append(columnsMapping.get(key).getColumn());
            buffer.append(",");
        }
        buffer.append(")");

        return buffer.toString();
    }


}
